class SpatialNode {
  Transform transform;
  SpatialNode parent;
  List<SpatialNode> _children;
  
  Collection<SpatialNode> get children() => _children;

  SpatialNode() {
    transform = null;
    parent = null;
    _children = new List<SpatialNode>();
  }

  void addChild(SpatialNode item) {
    if (item == null || item.parent == this)
      return;

    if (item.parent != null)
      item.parent.removeChild(item);
    
    assert(item.parent == null);
    
    item.parent = this;
    _children.add(item);
  }
  
  bool removeChild(SpatialNode item) {
    if (item == null || item.parent != this)
      return false;

    int index = _children.indexOf(item);
    assert(index != -1);
    if (index < _children.length - 1)
      _children[index] = _children.removeLast();
    else
      _children.removeLast();

    item.parent = null;
    
    return true;
  }
  
  void removeAllChildren() {
    for (final item in _children)
      item.parent = null;
    
    _children.clear();
  }
  
  void updateTransform(TransformContext context) {
    if (transform == null)
      return;

    transform.update(context.top);
    context.push(transform.matrix);
    _updateChildren(context);
    context.pop();
  }
  
  void _updateChildren(TransformContext context) {
    for (final item in _children)
      item.updateTransform(context);
  }
}